{
 "cells": [
  {
   "cell_type": "markdown",
   "source": [
    "## ReAct\n",
    "\n",
    "大名鼎鼎的AutoGPT项目就是基于ReAct模式实现，就是**推理+行动**模型，LLM大模型负责推理，控制行动达成目标，对于开发来说行动其实就是开发好的工具或者API，本章介绍LangChain如何实现ReAct模式。  \n",
    "![](./images/ReAct1.png)\n",
    "\n",
    "加载基础包\n",
    "\n",
    "```python\n",
    "from langchain.agents import load_tools\n",
    "from langchain.agents import initialize_agent\n",
    "from langchain.agents import AgentType\n",
    "from langchain_openai import OpenAI\n",
    "```\n",
    "\n",
    "这里使用openai模型"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "d41224b12204c6e3"
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "from dotenv import load_dotenv\n",
    "from langchain_community.agent_toolkits.load_tools import load_tools\n",
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "load_dotenv()\n",
    "\n",
    "llm = ChatOpenAI(\n",
    "    # 若没有配置环境变量，请用百炼API Key将下行替换为：api_key=\"sk-xxx\",\n",
    "    openai_api_key=os.getenv(\"DASHSCOPE_API_KEY\"),\n",
    "    openai_api_base=\"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n",
    "    model_name=\"qwen-max\",\n",
    "    temperature=0,\n",
    ")\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-10-31T10:16:17.013829Z",
     "start_time": "2024-10-31T10:16:14.365608Z"
    }
   },
   "id": "e257d4154877b2ca",
   "execution_count": 1
  },
  {
   "cell_type": "markdown",
   "source": [
    "这里加载两个langchain内置的工具， serpapi一个google搜索工具，llm-math是一个数学计算器，使用llm实现，所以这里加载工具的时候要传入使用的llm模型"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "a7a7c7bdc2589e68"
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "from langchain_core.tools import tool\n",
    "\n",
    "\n",
    "@tool\n",
    "def get_word_length(word: str) -> int:\n",
    "    \"\"\"\n",
    "    计算Word长度并返回计算结果\n",
    "    :param word: \n",
    "    :return: \n",
    "    \"\"\"\n",
    "    return len(word)\n",
    "\n",
    "\n",
    "@tool\n",
    "def send_sms(context: str, phone_number: str | list[str]) -> str:\n",
    "    \"\"\"\n",
    "    发送短信\n",
    "    :param context: \n",
    "    :param phone_number: \n",
    "    :return: \n",
    "    \"\"\"\n",
    "    print(f\"发短信，短信内容为：{context} 发送对象:{phone_number}\")\n",
    "    return \"发送成功\"\n",
    "\n",
    "tools = [get_word_length]\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-10-31T10:16:17.031932Z",
     "start_time": "2024-10-31T10:16:17.016717Z"
    }
   },
   "id": "9caba11f1facdd14",
   "execution_count": 2
  },
  {
   "cell_type": "markdown",
   "source": [
    "最后，初始化agent，agent类型选择AgentType.ZERO_SHOT_REACT_DESCRIPTION，代表ReAct模式。\n",
    "\n"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "ece0b180a57d1755"
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/var/folders/n2/51f_nb3j37g1wvdg9lmmxk200000gn/T/ipykernel_68246/2935361657.py:4: LangChainDeprecationWarning: The function `initialize_agent` was deprecated in LangChain 0.1.0 and will be removed in 1.0. Use :meth:`~Use new agent constructor methods like create_react_agent, create_json_agent, create_structured_chat_agent, etc.` instead.\n",
      "  agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001B[1m> Entering new AgentExecutor chain...\u001B[0m\n",
      "\u001B[32;1m\u001B[1;3m我需要使用get_word_length这个工具来计算\"agent\"这个词的长度。\n",
      "Action: get_word_length\n",
      "Action Input: \"agent\"\u001B[0m\n",
      "Observation: \u001B[36;1m\u001B[1;3m5\u001B[0m\n",
      "Thought:\u001B[32;1m\u001B[1;3m我现在知道了\"agent\"这个词的长度是5。\n",
      "Final Answer: \"agent\"这个词的长度是5。\u001B[0m\n",
      "\n",
      "\u001B[1m> Finished chain.\u001B[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": "{'input': 'agent长度？', 'output': '\"agent\"这个词的长度是5。'}"
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain.agents import initialize_agent, AgentType\n",
    "\n",
    "# verbose参数指定打印运行日志\n",
    "agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)\n",
    "agent.invoke(\"agent长度？\")\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-10-31T10:16:23.027485Z",
     "start_time": "2024-10-31T10:16:17.033927Z"
    }
   },
   "id": "37b7d47c05b33663",
   "execution_count": 3
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 使用聊天模型\n",
    "\n",
    "通过前面的例子知道agent需要选择一个大模型作为推理引擎，这里我们改成使用openai的聊天模型。"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "5db1cde41a819c60"
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001B[1m> Entering new AgentExecutor chain...\u001B[0m\n",
      "\u001B[32;1m\u001B[1;3mThought: 我需要使用get_word_length工具来计算单词\"agent\"的长度。\n",
      "Action:\n",
      "```\n",
      "{\n",
      "  \"action\": \"get_word_length\",\n",
      "  \"action_input\": \"agent\"\n",
      "}\n",
      "```\n",
      "\u001B[0m\n",
      "Observation: \u001B[36;1m\u001B[1;3m5\u001B[0m\n",
      "Thought:\u001B[32;1m\u001B[1;3m我现在知道\"agent\"的长度是5。\n",
      "\n",
      "Final Answer: \"agent\"的长度是5。\u001B[0m\n",
      "\n",
      "\u001B[1m> Finished chain.\u001B[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": "{'input': 'agent长度？', 'output': '\"agent\"的长度是5。'}"
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "agent = initialize_agent(tools, llm, agent=AgentType.CHAT_ZERO_SHOT_REACT_DESCRIPTION, verbose=True)\n",
    "agent.invoke(\"agent长度？\")\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-10-31T10:16:28.501759Z",
     "start_time": "2024-10-31T10:16:23.030042Z"
    }
   },
   "id": "2a8e7dcb562526bf",
   "execution_count": 4
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
